import time
import datetime
import time 
import gmssl.func as gmssl_func
from gmssl import sm4
import logging


# 获取unix时间，返回一个整数
# 在发BST时设置RUS参数，可以直接用这4字节数组
def get_unix_time():
    # 获取当前Unix时间戳（秒）
    timestamp = int(time.time())
    return timestamp

#获取unix时间，返回一个4字节的数组
#在发BST时设置RUS参数，可以直接用这4字节数组
def get_unix_time_hex():
    timestamp = int(time.time())
    ts_hex = "{0:08X}".format(timestamp)
    return ts_hex


#获取unix时间，返回一个4字节的数组
#在发BST时设置RUS参数，可以直接用这4字节数组
def get_unix_time_hex_ms():
    timestamp = int(time.time() * 1000)
    ts_hex = "{0:016X}".format(timestamp)
    return ts_hex

# 获取BCD时间以字符串方式返回，也同16进制字符串
# 20240902103205
def get_bcd_time():
    now = datetime.now()
    # 将日期和时间转换为字符串
    datetime_str = now.strftime('%Y%m%d%H%M%S')
    return datetime_str

def get_ms_part(stime):
    ms_part = int(stime * 1000) % 1000
    return ms_part  

def get_time_str(stime):
    ms_part = get_ms_part(stime)
    time_str = datetime.fromtimestamp(stime).strftime(f"%Y-%m-%d %H:%M:%S.{ms_part:03d}")
    return time_str

def get_now_str():
    now_time = time.time()
    now_str = get_time_str(now_time)
    return now_str

def get_delta_ms(start_time, end_time):
    delta_ms = (end_time - start_time) * 1000
    return delta_ms


def sm4_init_by_card_id_with_rootkey(hexcardid, root_key):
    sm4_crypt = sm4.CryptSM4(mode=sm4.SM4_ENCRYPT, padding_mode=3)  # 创建SM4加密对象
    by_hexcardid = bytes.fromhex(hexcardid)
    by_root_key = bytes.fromhex(root_key)
    ciphertext = b''
    comm = bytearray()
    if len(hexcardid) >= 8:
        sm4_crypt.set_key(by_root_key, sm4.SM4_ENCRYPT)  # 设置密钥
        comm.extend(by_hexcardid[0:8])
        xor_value = [i ^ 0XFF for i in by_hexcardid[0:8]]
        comm.extend(gmssl_func.list_to_bytes(xor_value))
        ciphertext = sm4_crypt.crypt_ecb(bytes(comm))  # 加密数据

    if len(hexcardid) >= 16:
        sm4_crypt.set_key(ciphertext, sm4.SM4_ENCRYPT)  # 设置密钥
        comm.clear()
        comm.extend(by_hexcardid[8:16])
        xor_value = [i ^ 0XFF for i in by_hexcardid[8:16]]
        comm.extend(gmssl_func.list_to_bytes(xor_value))
        ciphertext = sm4_crypt.crypt_ecb(bytes(comm))  # 加密数据

    return ciphertext


# SM4 Mac 填充， 首先填充0x80， 然后补齐0x00为16倍数
# ba 的类型为bytearray
def pad_to_multiple_of_16(ba):
    # 计算需要补充的字节数
    ba.append(0x80)
    pad_length = 16 - (len(ba) % 16)
    # 如果已经是16的倍数，则不需要补充
    if pad_length == 16:
        return ba
    # 使用零字节进行补充
    ba.extend(bytearray(pad_length))
    return ba

def split_bytearray(bytearr, chunk_size):
    return [bytearr[i:i+chunk_size] for i in range(0, len(bytearr), chunk_size)]

def sm4_mac(hex_key, hex_in_data, hex_init_vec = '0' * 32):
    by_key = bytes.fromhex(hex_key)
    by_data = bytes.fromhex(hex_in_data)
    by_init_vec = bytes.fromhex(hex_init_vec)
    by_tmp = bytearray(by_init_vec)
    by_data_padding = bytearray(by_data)
    by_data_padding = pad_to_multiple_of_16(by_data_padding)

    sm4_crypt = sm4.CryptSM4(mode=sm4.SM4_ENCRYPT, padding_mode=3)  # 创建SM4加密对象
    sm4_crypt.set_key(by_key, sm4.SM4_ENCRYPT)
    by_table = split_bytearray(by_data_padding, 16)
    for ba in by_table:
        for i in range(16):
            by_tmp[i] = by_tmp[i] ^ ba[i]
        by_tmp = sm4_crypt.crypt_ecb(bytes(by_tmp))
        by_tmp = bytearray(by_tmp)
        # print(f"by_tmp: {by_tmp.hex().upper()}")
    return bytes(by_tmp).hex().upper()[0:8]


def sm4_ecb_enc_dec(mode, hex_key, hex_in_data):
    '''
    sm4 ecb 模式加解密函数
    mode = 1 加密， mode=0 解密
    hex_key 密钥(32字节十六进制字符串)
    hex_in_data 输入数据(十六进制字符串，长度需为16的倍数)
    return: 输出数据(十六进制字符串)
    
    异常:
        ValueError: 输入参数无效时抛出
    '''
    # 验证输入参数
    if mode not in (0, 1):
        raise ValueError("mode参数必须为0(解密)或1(加密)")
    if not isinstance(hex_key, str) or len(hex_key) != 32:
        raise ValueError("密钥必须为32字节的十六进制字符串")
    if not isinstance(hex_in_data, str):
        raise ValueError("输入数据必须是字符串")
    
    # 如果长度不足16字节倍数，自动补0
    if len(hex_in_data) % 32 != 0:
        padding_length = 32 - (len(hex_in_data) % 32)
        hex_in_data = hex_in_data + '0' * padding_length
    
    try:
        by_key = bytes.fromhex(hex_key)
        by_data = bytes.fromhex(hex_in_data)
        sm4_crypt = sm4.CryptSM4(padding_mode=3)  # 创建SM4加密对象
        
        if mode == 1:
            sm4_crypt.set_key(by_key, sm4.SM4_ENCRYPT)
        elif mode == 0:
            sm4_crypt.set_key(by_key, sm4.SM4_DECRYPT)
            
        by_tmp = sm4_crypt.crypt_ecb(by_data)
        return by_tmp.hex().upper()
    except Exception as e:
        raise ValueError(f"SM4加解密失败: {str(e)}")

def get_bcc(byte_array):
    bcc = 0
    for b in byte_array:
        bcc = bcc ^ b
    return bcc

#用于标准车道CRC校验
def cal_crc16 (byte_data):
    crc_polynom = 0x8408
    crc = 0xFFFF
    for b in byte_data:
        crc = crc ^ b
        for i in range(8):
            if crc & 0x01 == 0x01:
               crc = (crc >> 1) ^ crc_polynom
            else:
               crc = crc >> 1
    crc = (~crc) & 0xFFFF
    return crc

if __name__ == '__main__':
#     print(get_bcd_time())
#     print(get_unix_time())
#     print(get_unix_time_hex())
#     print(get_unix_time_hex_ms())

    key = "00000000000000000000000000000000"
    # data = "BEB4B9FC9509BF1704"
    # # data = "BDF0D2E7BDF0D2E7" + "0000000000000263"
    data = "04D6811A0500"
    # data = "B4B9FC9509BF17040000000000000000"
    # aukey = sm4_init_by_card_id_with_rootkey(data, key)
    # print(aukey.hex().upper())
    print(sm4_mac(key, data, "810801066517D77B0000000000000000"))
    # data = "3D81A4E5B45C1CA90A3F76D2CF5E62D2"
    # # key = "00000000000000000000000000000000"
    # encryted_data = sm4_ecb_enc_dec(0, key, data)
    # print("encrypted data is :", encryted_data)
    # origin_data = sm4_ecb_enc_dec(1, key, data)
    # print("origin data is :", origin_data)
    # # consume_soft_mac1(c_rands='279D0498', consume_no='010C', imoney='00000000', timestamp='20250507155502', psam_termid='5C8339197585', payserial='73CB9C71')
